package com.ruoyi.business.controller;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.business.api.WeighBridgeApi;
import com.ruoyi.business.domain.Alarm;
import com.ruoyi.business.domain.DeliveryBillentryHand;
import com.ruoyi.business.domain.ReceivingBillentryHand;
import com.ruoyi.business.interceptor.BillEntryDto;
import com.ruoyi.business.interceptor.WebhookMessage;
import com.ruoyi.business.service.AlarmService;
import com.ruoyi.business.service.DeliveryBillentryHandService;
import com.ruoyi.business.service.ReceivingBillentryHandService;
import com.ruoyi.business.websocket.WebSocketServer;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.Month;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author JerryLu
 * @date 2024/8/4 17:28
 * @description
 */
@RestController
@RequestMapping("/system/information")
@Slf4j
public class InformationController extends BaseController {
    @Autowired
    WeighBridgeApi weighBridgeApi;

    @Autowired
    private ReceivingBillentryHandService receivingBillentryHandService;

    @Autowired
    private DeliveryBillentryHandService deliveryBillentryHandService;

    @Autowired
    private WebSocketServer webSocketServer;

    @Autowired
    private AlarmService alarmService;

    /**
     * 首页统计
     *
     * @param request
     * @return com.ruoyi.common.core.domain.R
     * @author JerryLu
     * @date 2024/8/21 15:47
     */
    @GetMapping("/statistics")
    public R statistics(HttpServletRequest request) throws Exception {
        String keywords = request.getParameter("keywords");
        String type = request.getParameter("type");
        String beginTime = null;
        String endTime = null;
        switch (keywords) {
            case "day":
                String day = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
                beginTime = DateUtils.dateTimeNow(day + " 00:00:00");
                endTime = DateUtils.dateTimeNow(day + " 23:59:59");
                break;
            case "month":
                LocalDate firstDayOfMonth = LocalDate.now().withDayOfMonth(1);
                String firstDayOfMonthStr = DateUtils.dateTime(DateUtils.toDate(firstDayOfMonth));
                LocalDate lastDayOfMonth = LocalDate.now().withDayOfMonth(firstDayOfMonth.lengthOfMonth());
                String lastDayOfMonthStr = DateUtils.dateTime(DateUtils.toDate(lastDayOfMonth));
                beginTime = DateUtils.dateTimeNow(firstDayOfMonthStr + " 00:00:00");
                endTime = DateUtils.dateTimeNow(lastDayOfMonthStr + " 23:59:59");
                break;
            case "season":
                LocalDate currentDate = LocalDate.now();
                Month currentMonth = currentDate.getMonth();
                int currentYear = currentDate.getYear();
                LocalDate firstDay, lastDay;
                if (currentMonth == Month.JANUARY || currentMonth == Month.FEBRUARY || currentMonth == Month.MARCH) {
                    firstDay = LocalDate.of(currentYear, Month.JANUARY, 1);
                    lastDay = LocalDate.of(currentYear, Month.MARCH, 31);
                } else if (currentMonth == Month.APRIL || currentMonth == Month.MAY || currentMonth == Month.JUNE) {
                    firstDay = LocalDate.of(currentYear, Month.APRIL, 1);
                    lastDay = LocalDate.of(currentYear, Month.JUNE, 30);
                } else if (currentMonth == Month.JULY || currentMonth == Month.AUGUST || currentMonth == Month.SEPTEMBER) {
                    firstDay = LocalDate.of(currentYear, Month.JULY, 1);
                    lastDay = LocalDate.of(currentYear, Month.SEPTEMBER, 30);
                } else {
                    firstDay = LocalDate.of(currentYear, Month.OCTOBER, 1);
                    lastDay = LocalDate.of(currentYear, Month.DECEMBER, 31);
                }
                beginTime = DateUtils.dateTimeNow(firstDay + " 00:00:00");
                endTime = DateUtils.dateTimeNow(lastDay + " 23:59:59");
                break;
            case "year":
                Calendar currCal = Calendar.getInstance();
                int currentYearF = currCal.get(Calendar.YEAR);

                Calendar calendar = Calendar.getInstance();
                calendar.clear();
                calendar.set(Calendar.YEAR, currentYearF);
                Date startDate = calendar.getTime();
                calendar.roll(Calendar.DAY_OF_YEAR, -1);
                Date endDate = calendar.getTime();
                beginTime = DateUtils.dateTimeNow(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, startDate) + " 00:00:00");
                endTime = DateUtils.dateTimeNow(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, endDate) + " 23:59:59");
                break;
        }
        if (Objects.equals(type, "alarm")) {
            QueryWrapper<Alarm> wrapper = Wrappers.query();
            wrapper.gt("create_time", beginTime);
            wrapper.lt("create_time", endTime);

            List<Alarm> alarmList = alarmService.list(wrapper);
            long smokeTotal = 0L;
            long fireTotal = 0L;
            if (!alarmList.isEmpty()) {
                smokeTotal = alarmList.stream().filter(obj -> obj.getType() == 1).count();
                fireTotal = alarmList.stream().filter(obj -> obj.getType() == 0).count();
            }

            JSONObject json = new JSONObject();
            json.put("smokeTotal", smokeTotal);
            json.put("fireTotal", fireTotal);
            String day = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
            String beginTime1 = DateUtils.dateTimeNow(day + " 00:00:00");
            String endTime1 = DateUtils.dateTimeNow(day + " 23:59:59");
            QueryWrapper<Alarm> query = Wrappers.query();
            query.select("node, create_time");
            query.gt("create_time", beginTime1);
            query.lt("create_time", endTime1);

            List<Alarm> list = alarmService.list(query);
            json.put("alarmList", list);
            return R.ok(json);
        } else {
            QueryWrapper<ReceivingBillentryHand> queryWrapper = Wrappers.query();
            queryWrapper.gt("create_time", beginTime);
            queryWrapper.lt("create_time", endTime);

            QueryWrapper<DeliveryBillentryHand> query = Wrappers.query();
            query.gt("create_time", beginTime);
            query.lt("create_time", endTime);

            List<ReceivingBillentryHand> receivingList = receivingBillentryHandService.list(queryWrapper);
            BigDecimal receivingTotal = receivingList.stream().map(ReceivingBillentryHand::getNetWeight).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            List<DeliveryBillentryHand> deliveryList = deliveryBillentryHandService.list(query);
            BigDecimal deliveryTotal = deliveryList.stream().map(DeliveryBillentryHand::getNetWeight).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

            JSONObject json = new JSONObject();
            JSONObject json1 = new JSONObject();
            json1.put("receivingTotal", receivingTotal);
            json1.put("deliveryTotal", deliveryTotal);

            List<BillEntryDto> receivingDTOs = convertToReceivingDto(receivingList);
            List<BillEntryDto> deliveryDTOs = convertToDeliveryDto(deliveryList); // 假设有转换方法

            List<BillEntryDto> mergedAndSortedList = mergeAndSort(receivingDTOs, deliveryDTOs);

//        String jsonArray = listToJson(mergedAndSortedList);
            json.put("list", mergedAndSortedList);
            json.put("totalJson", json1);

            return R.ok(json);
        }
    }

    public List<BillEntryDto> convertToReceivingDto(List<ReceivingBillentryHand> receivingList) {
        return receivingList.stream().map(rbh -> new BillEntryDto("采购收货", rbh.getMateriaName(), rbh.getQty(), rbh.getUnitName(), rbh.getNetWeight() != null ? rbh.getNetWeight() : new BigDecimal(BigInteger.ZERO), DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, rbh.getCreateTime()))).collect(Collectors.toList());
    }

    public List<BillEntryDto> convertToDeliveryDto(List<DeliveryBillentryHand> deliveryList) {
        return deliveryList.stream().map(rbh -> new BillEntryDto("销售发货", rbh.getMateriaName(), rbh.getQty(), rbh.getUnitName(), rbh.getNetWeight() != null ? rbh.getNetWeight() : new BigDecimal(BigInteger.ZERO), DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, rbh.getCreateTime()))).collect(Collectors.toList());
    }

    public List<BillEntryDto> mergeAndSort(List<BillEntryDto> receivingDTOs, List<BillEntryDto> deliveryDTOs) {
        List<BillEntryDto> mergedList = new ArrayList<>(receivingDTOs);
        mergedList.addAll(deliveryDTOs);
        mergedList.sort(Comparator.comparing(BillEntryDto::getCreateTime));
        return mergedList;
    }

    public String listToJson(List<BillEntryDto> mergedList) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(mergedList);
    }

    /**
     * 向地磅发送预称重信息
     *
     * @param jsonObject
     * @return com.ruoyi.common.core.domain.R
     * @author JerryLu
     * @date 2024/8/30 9:08
     */
    @PostMapping("/send")
    public R send(@RequestBody JSONObject jsonObject) throws MqttException {
        return weighBridgeApi.send(jsonObject);
    }

    /**
     * 设备告警消息推送
     *
     * @param header
     * @param body
     * @return org.springframework.http.ResponseEntity<java.lang.String>
     * @author JerryLu
     * @date 2024/9/19 8:46
     */
    @PostMapping(value = "/webhook")
    public ResponseEntity<String> VipWebhook(@RequestHeader HttpHeaders header, @RequestBody String body) {
        WebhookMessage receiveMessage = null;
        log.info("消息获取时间:{}, 请求头:{},请求体:{}", DateUtils.getTime(), JSON.toJSONString(header), body);
        try {
            receiveMessage = JSON.parseObject(body, WebhookMessage.class);
            JSONObject content = JSON.parseObject(receiveMessage.getBody().toString());
            if (StringUtils.isNotEmpty(content.getString("alarmType"))) {
                if (content.getString("alarmType").equals("motiondetect") ||
                        content.getString("alarmType").equals("smokeAlarm"))
                {
                    Alarm alarm = new Alarm();
                    if (Objects.equals(content.getString("alarmType"), "smokeAlarm")) {
                        alarm.setType(1);
                    } else {
                        alarm.setType(0);
                    }
                    String node = content.getString("channel") + "通道";
                    switch (content.getString("alarmType")) {
                        case "motiondetect":
                            alarm.setNode(node + "移动侦测告警");
                            break;
                        case "smokeAlarm":
                            alarm.setNode(node + "烟雾告警");
                            break;
                    }
                    alarm.setAlarmtype(content.getString("alarmType"));
                    alarm.setCreateTime(DateUtils.toTimeT(content.getString("alarmTime")));
                    alarmService.save(alarm);
                    // 发送消息到客户端
                    webSocketServer.sendMessage(receiveMessage.getBody().toString());
                }
            }

        } catch (Exception e) {
            //异常处理
            e.printStackTrace();
        }
        Map<String, String> result = new HashMap<>(1);
        assert receiveMessage != null;
        String messageId = receiveMessage.getHeader().getMessageId();
        result.put("messageId", messageId);
        final ResponseEntity<String> resp = ResponseEntity.ok(JSON.toJSONString(result));
        log.info("webhook返回的信息:{}", JSON.toJSONString(resp));
        return resp;
    }
}
